package groupd

import (
	"strings"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/common"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd"
)

// GroupAggregate 信息组聚合
type GroupAggregate struct {
	ddd.BaseAggregate
	GroupID         string `json:"group_id,omitempty"` // 唯一标识
	GroupDesc       `json:"desc,omitempty"`
	GroupStatus     `json:"status,omitempty"`
	GroupCtlParam   `json:"ctl_param,omitempty"`
	common.Operator `json:"operator,omitempty"`
}

// Repo 获取聚合根对应的仓储
func (g *GroupAggregate) Repo() GroupRepo {
	return g.Repository().(GroupRepo)
}

// UpdateDesc 修改信息组聚合中的信息描述
func (g *GroupAggregate) UpdateDesc(ctx ddd.Context, group GroupDesc) error {
	o := *g
	err := g.Repo().UpdateDesc(ctx, g.GroupID, group)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActUpdateDesc, map[string]interface{}{
		"old": o,
		"new": group,
	})
	return err
}

// UpdateCtlParam 修改信息组聚合中的控制参数描述
func (g *GroupAggregate) UpdateCtlParam(ctx ddd.Context, group GroupCtlParam) error {
	o := *g
	err := g.Repo().UpdateCtlParam(ctx, g.GroupID, group)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActUpdateCtl, map[string]interface{}{
		"old": o,
		"new": group,
	})
	return err
}

// Delete 删除信息组聚合
func (g *GroupAggregate) Delete(ctx ddd.Context) error {
	err := g.Repo().Delete(ctx, g.GroupID)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActDelete, g)
	return err
}

// Destroy 彻底删除信息组聚合
func (g *GroupAggregate) Destroy(ctx ddd.Context) error {
	err := g.Repo().DestroyByID(ctx, g.GroupID)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActDestroy, g)
	return err
}

// Recover 恢复已经删除的信息组聚合
func (g *GroupAggregate) Recover(ctx ddd.Context) error {
	err := g.Repo().RecoverByID(ctx, g.GroupID)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActRecover, g)
	return err
}

// StopCollecting 停止收集信息
func (g *GroupAggregate) StopCollecting(ctx ddd.Context) error {
	err := g.Repo().StopCollectingByID(ctx, g.GroupID)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActStopCollecting, g)
	return err
}

// StartCollecting 开始收集信息
func (g *GroupAggregate) StartCollecting(ctx ddd.Context) error {
	err := g.Repo().StartCollectingByID(ctx, g.GroupID)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActStartCollecting, g)
	return err
}

// QueryInfoPage 页查询组内的信息
func (g *GroupAggregate) QueryInfoPage(ctx ddd.Context, pi common.PageInfo) (npi common.PageResult, result []GroupInfoEntity, err error) {
	return g.Repo().QueryInfoPage(ctx, g.GroupID, pi)
}

// QueryPage 分页获取组内信息列表：根据唯一标识获取下一页指定数量的信息实体集合
func (g *GroupAggregate) QueryPage(ctx ddd.Context, gs GroupSearch, pi common.PageInfo) (npi common.PageResult, result []GroupAggregate, err error) {
	return g.Repo().QueryPage(ctx, gs, pi)
}

// Empty 清空组内信息
// 发出清空组内信息事件
func (g *GroupAggregate) Empty(ctx ddd.Context) error {
	err := g.Repo().Empty(ctx, g.GroupID)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActEmpty, g.GroupID)
	return err
}

// Refresh 刷新组内信息
// num 指定刷新数量，倒序的方式根据规则重新匹配指定数量的信息，num指定为0 则刷新所有符合规则的数据
// 手动指定的组只刷新排序id
// 发出刷新组内信息事件
func (g *GroupAggregate) Refresh(ctx ddd.Context, num int) error {
	err := g.Repo().Refresh(ctx, g.GroupID, num)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActRefresh, g.GroupID)
	return err
}

// ExistsForInfo 检查信息编号是否存在组内
// 返回存在的信息编号切片
func (g *GroupAggregate) ExistsForInfo(ctx ddd.Context, infoids []string) ([]string, error) {
	return g.Repo().ExistsForInfo(ctx, g.GroupID, infoids)

}

// AppendInfo 向组内追加信息
// infoid 信息编号
// weight 权重值
// 加入组的信息首先要获取一个排序编号InfoNum+1，
// 然后根据权重
// 发出追加信息事件
// 如果组正处于刷新状态需要等待刷新完成后再次添加，可以采用异步添加实现
func (g *GroupAggregate) AppendInfo(ctx ddd.Context, info GroupInfoDesc) error {
	return g.Repo().AppendInfos(ctx, g.GroupID, []GroupInfoDesc{info})
}

// AppendInfos 向组内追加信息
// 发出追加信息事件
// 如果组正处于刷新状态需要等待刷新完成后再次添加
func (g *GroupAggregate) AppendInfos(ctx ddd.Context, infos []GroupInfoDesc) error {
	err := g.Repo().AppendInfos(ctx, g.GroupID, infos)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActAppendInfo, map[string]interface{}{
		"groupid": g.GroupID,
		"infos":   infos,
	})
	return err
}

// DeleteInfos 删除组内信息
// infoid 指定要删除的信息
// 发出删除信息事件，删除信息需要从新调整排序组内数量重新调整
func (g *GroupAggregate) DeleteInfos(ctx ddd.Context, infoids []string) error {
	err := g.Repo().DeleteInfos(ctx, g.GroupID, infoids)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActDeleteInfo, map[string]interface{}{
		"groupid": g.GroupID,
		"infoids": infoids,
	})
	return err
}

// UpdateInfoWeight 更新组内指定信息的权重值
func (g *GroupAggregate) UpdateInfoWeight(ctx ddd.Context, giid string, weight int) error {
	err := g.Repo().UpdateInfoWeight(ctx, giid, weight)
	if err != nil {
		return err
	}
	g.Trigger(ctx, EvtTypGroup, EvtActUpdateInfoWeight, map[string]interface{}{
		"groupid": g.GroupID,
		"giid":    giid,
		"weight":  weight,
	})
	return err
}

// MatchGroupInfo 信息是否匹配组规则
func (g *GroupAggregate) MatchGroupInfo(i *InfoColl) bool {
	if g.Kind == GroupKindManual {
		return false
	}
	if len(g.Rules) == 0 {
		return false
	}
	for _, r := range g.Rules {
		if r.ColumnID != "" && r.ColumnID != i.ColumnID {
			continue
		}
		if r.Org != "" && r.Org != i.Org {
			continue
		}
		if r.Own != "" && r.Own != i.Owner {
			continue
		}
		if r.Tags != nil && len(r.Tags) > 0 {
			if len(r.Tags) > len(i.Tags) {
				continue
			}
			for _, rt := range r.Tags {
				if _, ok := i.Tags[rt]; !ok {
					continue
				}
			}
		}
		if r.Key != "" {
			if !strings.Contains(i.Content, r.Key) {
				continue
			}

		}
		return true
	}
	return false
}
